<!DOCTYPE html>
<html>
    <head>
    <title>AtGame</title>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="favicon.ico"/>
    <link rel="bookmark" href="favicon.ico"/>
    <link rel="stylesheet" href="core.css" />
 
    <style>
        #stats { position: absolute; top:0; left: 0 }
        #stats #fps { background: transparent !important }
        #stats #fps #fpsText { color: #ccc !important }
        #stats #fps #fpsGraph { display: none }
    </style>
    
    <script src="//cdn.jsdelivr.net/npm/eruda"></script>
    
    <script type="text/javascript" src="./libs/stats.min.js"></script>
    <script type="text/javascript" src="./libs/jpg.js"></script>
    <script type="text/javascript" src="./base.js"></script>
    <script type="text/javascript" src="./math.js"></script>
    <script type="text/javascript" src="./input.js"></script>
    <script type="text/javascript" src="./binaryreader.js"></script>
    <script type="text/javascript" src="./mdx/parser.js"></script>
    <script type="text/javascript" src="./mdx/tgatexture.js"></script>
    <script type="text/javascript" src="./mdx/blptexture.js"></script>
    <script type="text/javascript" src="./mdx/animation.js"></script>
    <script type="text/javascript" src="./mdx/particleemitter.js"></script>
    
    <script type="text/javascript">
            
        function onclick1(){
            var fileInput = document.createElement( 'input' );
            fileInput.type = 'file';
            fileInput.accept="image/*";
            fileInput.addEventListener( 'change', function ( event ) {
                var file = event.target.files[0];//事件目标
                function printObject(o) {
                    var out = '';
                        for (var p in o) {
                        out += p + ': ' + o[p] + '\n';
                    }
                    alert(out);
                }
                printObject(file);
            } );
            fileInput.click();
        }
        
        function onOpenMdx(index){
            var list = window["MPQList"];
            var idx = parseInt(index);
            if(list && list[idx]){
                LoadModel(list[idx]);
            }
        }
        
        var getStatus = (function()
        {
            var opened = true;
            return function doSwitch(){
                var old = opened;
                opened = !opened;
                return old;
           };
        })();
        
        function onClick2()
        {
            var canvas = document.getElementById("canvas")
            if(canvas){
                var isOpened = getStatus()
                if(isOpened){
                    var outline = document.getElementById("outline")
                    outline.style.display="none";
                    var showBtn = document.getElementById("show ountline")
                    showBtn.style.display="block";
                    
                    canvas.style.width = "100%";
                }
                else{
                    var outline = document.getElementById("outline")
                    outline.style.display="block";
                    var showBtn = document.getElementById("show ountline")
                    showBtn.style.display="none";
                    canvas.style.width = "75%";
                }
                
                var gl = window["webgl"];
                if (gl){
                    ResetViewport(canvas, gl);
                }
            }
        }
        
        var getStatusB1 = (function()
        {
            var opened = true;
            return function doSwitch(){
                var old = opened;
                opened = !opened;
                return old;
           };
        })();
            
        function onClick3(d)
        {
            if(d.openState === undefined || d.openState == true){
                d.openState = false;
                var t1 = document.getElementById(d.id + "_content")
                t1.style.display="none";
                d.innerHTML = d.innerHTML.replace("◢", "◤");
                
            }
            else{
                d.openState = true;
                var t1 = document.getElementById(d.id + "_content")
                t1.style.display="block";
                d.innerHTML = d.innerHTML.replace("◤", "◢");
            }
        }
        
        window.onkeydown = function(event) 
        {
            var camera = window["camera"];
            var Key = window["Key"];
            if(camera && Key){
                if(event.keyCode === Key.W)
                    camera.position.x += 5.0;
                else if(event.keyCode === Key.S)
                    camera.position.x -= 5.0;
                else if(event.keyCode === Key.E)
                    camera.position.y += 5.0;
                else if(event.keyCode === Key.D)
                    camera.position.y -= 5.0;
                else if(event.keyCode === Key.R)
                    camera.position.z += 5.0;
                else if(event.keyCode === Key.F)
                    camera.position.z -= 5.0;

                if(event.keyCode === Key.U)
                    camera.lookAt.x += 5.0;
                else if(event.keyCode === Key.J)
                    camera.lookAt.x -= 5.0;
                else if(event.keyCode === Key.I)
                    camera.lookAt.y += 5.0;
                else if(event.keyCode === Key.K)
                    camera.lookAt.y -= 5.0;
                else if(event.keyCode === Key.O)
                    camera.lookAt.z += 5.0;
                else if(event.keyCode === Key.L)
                    camera.lookAt.z -= 5.0;
            }
        }
        
        
        function ChangeMaterial(value){
            var model = window["model"];
            var chunks = model.parser.chunks;
            var innerHTML = "";
            var layers = chunks.MTLS.elements[parseInt(value)].layers;
            for ( var i = 0, l = layers.length; i < l; ++i){
                var layer = layers[i];
                var filterMode = layer.filterMode;
                
                // filterMode {
                //  0 - Opaque
                //  1 - 1bit Alpha
                //  2 - Blend
                //  3 - Additive
                //  4 - AddAlpha
                //  5 - Modulate
                //  6 - Modulate2x
                // }
                
                innerHTML += "<p>第" + (i + 1) + "层混合模式:";
                switch (filterMode) {
                case 0:
                    innerHTML += "不透明</p>";
                    break;
                case 1:
                    innerHTML += "透明AlphaTest</p>";
                    break;
                case 2:
                    innerHTML += "Alpha Blend</p>";
                    break;
                case 3:
                    innerHTML += "颜色叠加</p>";
                    break;
                case 4:
                    innerHTML += "Alpha Blend颜色叠加</p>";
                    break;
                case 5:
                    innerHTML += "ZERO,SRC_COLOR调制</p>";
                    break;
                case 6:
                    innerHTML += "DST_COLOR SRC_COLOR调制</p>";
                    break;
                }
                
                
                // ShadingFlags {
                //  #1   - Unshaded
                //  #2   - SphereEnvironmentMap
                //  #4   - ???
                //  #8   - ???
                //  #16  - TwoSided
                //  #32  - Unfogged
                //  #64  - NoDepthTest
                //  #128 - NoDepthSet
                // }

                if(layer.noDepthTest === 0){
                    innerHTML += "<p>深度测试:开</p>"
                }else{
                    innerHTML += "<p>深度测试:关</p>"
                }
                
                if(layer.noDepthSet === 0){
                    innerHTML += "<p>深度写入:开</p>"
                }else{
                    innerHTML += "<p>深度写入:关</p>"
                }
                
                if(layer.twoSided === 0){
                    innerHTML += "<p>双面:关</p>"
                }else{
                    innerHTML += "<p>双面:开</p>"
                }
            }
                
            var t1DescDiv = document.getElementById("t1_content_desc");
            if (t1DescDiv){
                t1DescDiv.innerHTML = innerHTML
            }
        }
        
        function SetMatrialInfo(parser)
        {
            var chunkDiv = document.getElementById("t1_content");
            var chunks = parser.chunks;
            var matNb = chunks.MTLS.elements.length;
            var innerHTML = "<select class='snippets' onchange='ChangeMaterial(this.value)'>";
            for ( var i = 0; i < matNb; ++i ) {
                innerHTML += "<option value=" + i +">Material" + i + "</option>";
            }
            innerHTML += "</select>";
            innerHTML += "<div id='t1_content_desc'></div>"
            
            chunkDiv.innerHTML = innerHTML;
            // 默认设置
            ChangeMaterial("0");
        }
        
        
        function ChangeShowGeometry(idx){
            var model = window["model"];
            if (model.meshs[idx].visable === true){
                model.meshs[idx].visable = false;
            }else{
                model.meshs[idx].visable = true;
            }
            
            SetGeometryInfo(model.parser);
        }
        
        function SetGeometryInfo(parser)
        {
            var chunkDiv = document.getElementById("t2_content");
            var chunks = parser.chunks;
            var geoNb = chunks.GEOS.elements.length;
            var innerHTML = "<p>几何体:" + geoNb + "</p>";
            
            var model = window["model"];
            for (var i = 0; i < geoNb; ++i){
                var name = "geomerty" + i;
                var visable = "";
                if (model.meshs[i].visable === true){
                    visable = " checked=true ";
                }
                innerHTML += "<input type='checkbox' name='geomerty' value='" + i +"'" + visable + " onchange='ChangeShowGeometry(this.value)'>" + name+ "<br>";
            }
            
            var facesNb = 0;
            var vertexNb = 0;
            var normalNb = 0;
            var uvNb = 0;
            for (var i = 0; i < geoNb; ++i){
                if (model.meshs[i].visable !== true){
                    continue;
                }
                
                facesNb += chunks.GEOS.elements[i].faces.length;
                vertexNb += chunks.GEOS.elements[i].vertices.length;
                normalNb += chunks.GEOS.elements[i].normals.length;
                for (var j = 0; j < chunks.GEOS.elements[i].textureCoordinateSets.length; ++j){
                    uvNb += chunks.GEOS.elements[i].textureCoordinateSets[j].length;
                }
            }
            innerHTML += "<p>三角面:" + facesNb + "</p>";
            innerHTML += "<p>顶点数:" + vertexNb + "</p>";
            innerHTML += "<p>法线数:" + normalNb + "</p>";
            innerHTML += "<p>UV数:" + uvNb + "</p>";
            chunkDiv.innerHTML = innerHTML;
        }
        
        function ChangeChunk(key)
        {
            var model = window["model"];
            if(model && model.parser)
            {
                var chunks = model.parser.chunks;
                var p = document.getElementById("snippets_chunk_number");
                if(p){
                    if (chunks[key].elements)
                        p.innerText = "元素个数:" + chunks[key].elements.length;
                    else
                        p.innerText = "元素个数:0";
                }
            }
        }
        
        function SetChunkData(parser)
        {
            var chunkDiv = document.getElementById("t4_content");
            var chunks = parser.chunks;
            var innerHTML = "<select class='snippets' onchange='ChangeChunk(this.value)'>";
            for ( var key in chunks ) {
                innerHTML += "<option>" + key + "</option>";
            }
            innerHTML += "</select>";
            innerHTML += "<p id='snippets_chunk_number'>元素个数:0</p>";
            chunkDiv.innerHTML = innerHTML;
            
            //var se = document.createElement("select");
            //se.options[0] = new Option("加载项1", "");
            //se.options[1] = new Option("加载项2", "");
            //se.size = "2";
            //var object = chunkDiv.appendChild(se);
        }
        
        function ChangeShowTexture(key)
        {
            var textures = window["textures"];
            if (textures && textures.elements.length > key) {
                var canvas = document.getElementById("test")
                if(canvas){
                    var data = textures.elements[key];
                    var width = data.width, height = data.height, imagedata = data.imagedata;
                    var ctx = canvas.getContext('2d');
                    if (width > canvas.width) {
                        canvas.width = width;
                    }
                    if (height > canvas.height) {
                        canvas.height = height;
                    }
                    
                    //绘制透明底图
                    var R = Math.floor(canvas.height / 8);
                    var C = Math.floor(canvas.width / 8);
                    for (var row = 0; row < R; row ++){
                        for (var column = 0; column < C; column ++){
                            // coordinates of the top-left corner
                            var x = column * 8;
                            var y = row * 8;
                            
                            if (row%2 == 0)
                            {
                                if (column%2 == 0)
                                    ctx.fillStyle = "#ccc";
                                else
                                    ctx.fillStyle = "white";
                            }else{
                                if (column%2 == 0)
                                    ctx.fillStyle = "white";
                                else
                                    ctx.fillStyle = "#ccc";
                            }
                            ctx.fillRect(x, y, 8, 8);
                        }
                    }
                    
                    var newCanvas = document.createElement('canvas');
                    newCanvas.width = width, newCanvas.height = height;
                    var newCtx = newCanvas.getContext('2d');
                    var imgdata = newCtx.getImageData(0, 0, width, height);
                    var pixels = imgdata.data;
                    var i = 0;
                    for (var i = 0; i < imagedata.length; ++i){
                        pixels[i] = imagedata[i];
                    }
                    newCtx.putImageData(imgdata, 0, 0);
                    ctx.drawImage(newCanvas, 0, 0, width, height, 0, 0,canvas.width, canvas.height);
                }
            }
        }
        
        function SetTextureInfo(parser)
        {
            var chunkDiv = document.getElementById("t3_content");
            var chunks = parser.chunks;
            var texNb = chunks.TEXS.elements.length;
            var innerHTML = "<p>纹理:" + texNb + "张</p>";
            innerHTML += "<select class='snippets' onchange='ChangeShowTexture(this.value)'>";
            for ( var i = 0; i < texNb; ++i ) {
                if (chunks.TEXS.elements[i].replaceableId) {
                    var replaceableId = chunks.TEXS.elements[i].replaceableId ;
                    if (replaceableId == 1) {
                        innerHTML += "<option value=" + i +">" + "ReplaceableTextures\TeamColor\TeamColor.blp" + "</option>";
                    }else if(replaceableId == 2) {
                        innerHTML += "<option value=" + i +">" + "ReplaceableTextures\TeamGlow\TeamGlow.blp" + "</option>";
                    }
                }else {
                    innerHTML += "<option value=" + i +">" + chunks.TEXS.elements[i].path + "</option>";
                }
            }
            innerHTML += "</select>";
            innerHTML += "<div style='width:99%;overflow: auto;'><canvas id='test' style='width:100%;background:transparent';></canvas></div>"
            chunkDiv.innerHTML = innerHTML;
        }
        
        function SetBoneInfo(parser)
        {
            var chunkDiv = document.getElementById("t5_content");
            var chunks = parser.chunks;
            var boneNb = chunks.BONE.elements.length
            var innerHTML = "";
            for (var i = 0; i < boneNb; ++i){
                var bone = chunks.BONE.elements[i];
                var node = bone.node;
                innerHTML += "<p>骨骼Id:" + node.objectId + "名字:" + node.name + " 父骨骼id:" + node.parentId + "</p>";
            }
            chunkDiv.innerHTML = innerHTML;
        }
        
        function ChangeSequence(index){
            g_AnimatinIndex = parseInt(index);
            g_Time = 0;
        }
        
        function ChangeSequenceSpeed(value){
            var playSpeedDiv = document.getElementById("playSpeed");
            if(playSpeedDiv){
                playSpeedDiv.innerHTML = "播放速度:" + value + "x";
                g_Speed = value;
            }
        }
        
        function SetSequenceInfo(parser)
        {
            var chunkDiv = document.getElementById("t6_content");
            var chunks = parser.chunks;
            var seqsNb = chunks.SEQS.elements.length
            var innerHTML = "<select class='snippets' onchange='ChangeSequence(this.value)'>";
            for (var i = 0; i < seqsNb; ++i){
                var sequence = chunks.SEQS.elements[i];
                innerHTML += "<option value=" + i +">" + sequence.name + "</option>";
            }
            innerHTML += "</select>";
            innerHTML += "<p id='playSpeed'>播放速度:1x</p><input type='range' name='points' value='1' min='1' max='5' onchange='ChangeSequenceSpeed(this.value)'/>";
            chunkDiv.innerHTML = innerHTML;
        }
        
        function ClearModel()
        {
            var gl = window["webgl"];
        
            if (window["model"] === undefined){
                window["model"] = {
                    isLoad : false,
                }
            }
            else{
                var model = window["model"];
                if(model.isLoad === true){
                    
                    for (var i = 0, l = model.meshs.length; i < l; ++i ){
                        var mesh = model.meshs[i];
                        gl.deleteBuffer(mesh.ib)
                        mesh.ib = undefined
                        gl.deleteBuffer(mesh.vb)
                        mesh.vb = undefined
                    }
                    model.meshs = undefined
                    model.parser = undefined
                    model.isLoad = false
                    model.chacheNodeMatArray = undefined
                    if(model.boneTexture){
                        gl.deleteTexture(model.boneTexture);
                        model.boneTexture = undefined;
                    }
                    
                    if(model.hwbones){
                        model.hwbones = undefined;
                    }
                }
            }
            
            if (window["materials"] === undefined){
                window["materials"] = {
                    isLoad : false,
                }
            }else{
                window["materials"] = {
                    isLoad : false,
                }
            }
            
            if (window["textures"] === undefined){
                window["textures"] = {
                    isLoad : false,
                    elements : [],
                }
            }
            else{
                var textures = window["textures"];
                if(textures.isLoad == true){
                    for (var i = 0, l = textures.elements.length; i < l; ++i){
                        gl.deleteTexture(textures.elements[i].texture);
                    }
                    window["textures"] = {
                        isLoad : false,
                        elements : [],
                    }
                }
            }
        }
        
        function LoadModel(modelPath)
        {
            ClearModel()
        
            function onLoadModel(e)
            {
                var status = e.target.status;
            
                if (status === 200) {
                    var src = e.target.response;
                    
                    var gl = window["webgl"];
                    var model = window["model"];
                    var materials = window["materials"];
                    
                    var parser = Mdx.Parser(new BinaryReader(src));
                    model.parser = parser;
                    
                    model.meshs = [];
                    for (var i = 0, l = parser.chunks.GEOS.elements.length; i < l; ++i){
                        var mesh = { visable : true };
                        var geoset = parser.chunks.GEOS.elements[i];
                        // 创建索引顶点
                        (function(u16Array){
                            var ib = gl.createBuffer();
                            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ib);
                            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, u16Array, gl.STATIC_DRAW);
                            
                            mesh.ib = ib;
                            mesh.drawCount = u16Array.length;
                        })(geoset.faces);
                        
                        // 创建顶点
                        (function(posFloatArray, uvFloatArray, matrixGroups, matrixIndexes, vertexGroups){
                            
                            // 创建蒙皮骨骼索引,骨骼数量
                            var vertices = vertexGroups.length;
                            var boneIndices = new Float32Array(vertices * 4);
                            var boneNumbers = new Float32Array(vertices);
                            var tempMatrixGroups = [];
                            var i, j, k, l;
                            
                            // Parse the bone indices
                            for (i = 0, l = matrixGroups.length, k = 0; i < l; i++) {
                                tempMatrixGroups.push(matrixIndexes.subarray(k, k + matrixGroups[i]));
                                k += matrixGroups[i];
                            }
                            
                            for (i = 0, l = vertices, k = 0; i < l; i++) {
                                var matrixGroup = tempMatrixGroups[vertexGroups[i]];
                                var count = 0;
                                
                                // 1 is added to every index for shader optimization.
                                for (j = 0; j < 4; j++) {
                                    if (matrixGroup && j < matrixGroup.length) {
                                        boneIndices[k] = matrixGroup[j] + 1;
                                        count += 1;
                                    } else {
                                        boneIndices[k] = 0;
                                    }
                                    k += 1;
                                }
                                boneNumbers[i] = count;
                                
                            }
                        
                            var verticesArray = new Float32Array(posFloatArray.length + uvFloatArray.length + boneIndices.length + boneNumbers.length);
                            for(i = 0, j = 0, k = 0, l = 0, idx = 0; l < vertices; i+=3, j+=2, k+=4, ++l)
                            {
                                verticesArray[idx++] = posFloatArray[i];
                                verticesArray[idx++] = posFloatArray[i+1];
                                verticesArray[idx++] = posFloatArray[i+2];
                                verticesArray[idx++] = uvFloatArray[j];
                                verticesArray[idx++] = uvFloatArray[j+1];
                                verticesArray[idx++] = boneIndices[k];
                                verticesArray[idx++] = boneIndices[k+1];
                                verticesArray[idx++] = boneIndices[k+2];
                                verticesArray[idx++] = boneIndices[k+3];
                                verticesArray[idx++] = boneNumbers[l];
                            }
                            
                            var vb = gl.createBuffer();
                            gl.bindBuffer(gl.ARRAY_BUFFER, vb);
                            gl.bufferData(gl.ARRAY_BUFFER, verticesArray, gl.STATIC_DRAW);
                         
                            mesh.vb = vb;
                        })(geoset.vertices, geoset.textureCoordinateSets[0], geoset.matrixGroups, geoset.matrixIndexes, geoset.vertexGroups);
                        
                        mesh.mId = geoset.materialId;
                        model.meshs[i] = mesh; 
                    }
                    
                    materials.elements = []
                    for (var i = 0, l = parser.chunks.MTLS.elements.length; i < l; ++i){
                        var material = { renderPass : [] };
                        for(var j = 0, len = parser.chunks.MTLS.elements[i].layers.length; j < len; ++j){
                            var layer = parser.chunks.MTLS.elements[i].layers[j];
                            var pass = {};
                            pass.tId = layer.textureId;
                            pass.filterMode = layer.filterMode;
                            pass.noDepthSet = layer.noDepthSet;
                            pass.noDepthTest = layer.noDepthTest;
                            pass.twoSided = layer.twoSided;
                            material.renderPass.push(pass);
                        }
                        
                        materials.elements.push(material);
                    }
                    materials.isLoad = true;
                    
                    /*var camera = window["camera"];
                    if (parser.chunks.CAMS.elements.length > 0){
                        var theCams = parser.chunks.CAMS.elements[0];
                        camera.position.x = theCams.position[0];
                        camera.position.y = theCams.position[1];
                        camera.position.z = theCams.position[2];
                        camera.lookAt.x = theCams.targetPosition[0];
                        camera.lookAt.y = theCams.targetPosition[1];
                        camera.lookAt.z = theCams.targetPosition[2];
                    }*/
                    
                    SetMatrialInfo(parser);
                    SetGeometryInfo(parser);
                    SetChunkData(parser);
                    SetTextureInfo(parser);
                    SetBoneInfo(parser);
                    SetSequenceInfo(parser);
                    
                    var textures =  window["textures"].elements;
                    for (var i = 0, l = parser.chunks.TEXS.elements.length; i < l; ++i){
                        textures.push(-1);
                        if (parser.chunks.TEXS.elements[i].path.length > 0){
                            getRequest("MPQ/" + parser.chunks.TEXS.elements[i].path, 
                                       true, 
                                       (function(idx){ 
                                            return function(e){ 
                                                onLoadBlpTexture(e, idx); 
                                            };
                                       })(i), onError, onProgress);
                        }else{
                            
                            if(parser.chunks.TEXS.elements[i].replaceableId == 1){
                                getRequest("MPQ/ReplaceableTextures/TeamColor/TeamColor00.blp", 
                                       true, 
                                       (function(idx){ 
                                            return function(e){ 
                                                onLoadBlpTexture(e, idx); 
                                            };
                                       })(i), onError, onProgress);
                            }else if(parser.chunks.TEXS.elements[i].replaceableId == 2){
                                getRequest("MPQ/ReplaceableTextures/TeamGlow/TeamGlow01.blp", 
                                       true, 
                                       (function(idx){ 
                                            return function(e){ 
                                                onLoadBlpTexture(e, idx); 
                                            };
                                       })(i), onError, onProgress);
                                /*
                                // team color
                                var imagedata  = new Uint8Array(4);
                                imagedata[0] = 255;
                                imagedata[1] = 255;
                                imagedata[2] = 0;
                                imagedata[3] = 255;
                                var texture = gl.createTexture();
                                gl.bindTexture(gl.TEXTURE_2D, texture);
                                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
                                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
                                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
                                gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
                                gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, imagedata);
                                gl.generateMipmap(gl.TEXTURE_2D);
                                
                                textures[i] = texture;*/
                            }
                        }
                    }
                    
                    model.isLoad = true;
                    g_AnimatinIndex = 0;
                }
            }
            
            function onLoadTgaTexture(e)
            {
                var status = e.target.status;
                if (status === 200) {
                    var src = e.target.response;
                    
                    var gl = window["webgl"];
                    var textures = window["textures"].elements;
                    
                    DecodeTGA(
                        src, 
                        function(msg){ alert(msg); },
                        function(width, height, imagedata){
                            var texture = gl.createTexture();
                            gl.bindTexture(gl.TEXTURE_2D, texture);
                            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
                            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
                            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
                            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
                            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
                            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, imagedata);
                            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
                            gl.generateMipmap(gl.TEXTURE_2D);

                            textures[idx] = { 'texture' : texture, 'width' : width, 'height' : height, 'imagedata' : imagedata };
                        } 
                    );
                }
            }
            
            function onLoadBlpTexture(e, idx)
            {
                var status = e.target.status;
                if (status === 200) {
                    var src = e.target.response;
                    
                    var gl = window["webgl"];
                    var textures = window["textures"].elements;
                    
                    DecodeBLP(
                        src, 
                        function(msg){ alert(msg); },
                        function(width, height, imagedata){
                            var texture = gl.createTexture();
                            gl.bindTexture(gl.TEXTURE_2D, texture);
                            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
                            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
                            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
                            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
                            //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
                            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, imagedata);
                            //gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
                            gl.generateMipmap(gl.TEXTURE_2D);

                            textures[idx] = { 'texture' : texture, 'width' : width, 'height' : height, 'imagedata' : imagedata };
                            
                            var allLoaded = true;
                            for(var i = 0; i < textures.length; ++i){
                                if(textures[i] === -1) {
                                    break;
                                }
                            }
                            if (allLoaded) {
                                ChangeShowTexture(0);
                            }
                        } 
                    );
                }
            }
            
            function onError(e)
            {
                var status = e.target.status;
                alert(status);
            }

            function onProgress(e)
            {
                //if (e.target.status === 200) {
                //    var msg = "" + e.loaded + " " + e.total + " " + e.lengthComputable;
                //    alert(msg);
                //}
            }
            
            getRequest(modelPath, true, onLoadModel, onError, onProgress);
            //getRequest("golemstatue.tga", true, onLoadTgaTexture, onError, onProgress);
        }
        
        function LoadMPQList()
        {
            function onLoadMPQList(e)
            {
                var status = e.target.status;
                if (status === 200) {
                    var src = e.target.response;
                    var lines = src.split("\n");
                    window["MPQList"] = lines;
                    var options = document.getElementById("options")
                    options.innerHTML += "<hr/>";
                    for (i in lines){
                        var line = lines[i]
                        if( line != ""){
                            options.innerHTML += "<div class='option' mid='" + i + "' onclick=onOpenMdx(this.getAttribute('mid'))>记录:" + line + "</div>";
                        }
                    }
                }
            }
        
            function onError(e){
                var status = e.target.status;
                alert(status);
            }

            function onProgress(e){
                //if (e.target.status === 200) {
                //    var msg = "" + e.loaded + " " + e.total + " " + e.lengthComputable;
                //    alert(msg);
                //}
            }
            
            getRequest("ResourceList.txt", false, onLoadMPQList, onError, onProgress);
        }
        
        var g_Time = 0;
        var g_AnimatinIndex = 0;
        var g_Speed = 1;
        
        function renderMesh( mvp )
        {
            var gl = window["webgl"];
            var shader = window["mdxShader"];
            
            var model = window["model"];
            var textures = window["textures"];
            var materials = window["materials"];
        
            if(shader === undefined)
                return;
        
            if(model === undefined || materials === undefined || textures === undefined ||
               model.isLoad !== true || materials.isLoad !== true || textures.elements.length <= 0)
                return;
                
            // 设置shader
            gl.useProgram(shader.program);
            // 设置shader uniform
            gl.uniformMatrix4fv(shader.u_MVP, false, mvp);
            
            var maxTextureUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
            if (model.boneTexture)
            {// 设置蒙皮矩阵纹理
                gl.activeTexture(gl['TEXTURE'+(maxTextureUnits-1)]);
                gl.bindTexture(gl.TEXTURE_2D, model.boneTexture);
                gl.uniform1i(shader.u_texboneMap, (maxTextureUnits-1));
                gl.uniform1f(shader.u_texboneMapTexelSize, model.texelFraction);
                gl.uniform1f(shader.u_texboneMapmatrixSize, model.matrixFraction); 
            }
            
            // 更新动作
            //PlaySequence(g_AnimatinIndex, g_Time);
            //PlayParticle(g_AnimatinIndex, g_Time);
            //g_Time += 15 * g_Speed;
            
            for (var i = 0, l = model.meshs.length; i < l; ++i){
                var mesh = model.meshs[i];
                if (mesh.visable === false){
                    continue;
                }
                
                // 设置顶点
                gl.bindBuffer(gl.ARRAY_BUFFER, mesh.vb);
                gl.enableVertexAttribArray(shader.va_posId);
                gl.vertexAttribPointer(shader.va_posId, 3, gl.FLOAT, false, 40, 0);
                gl.enableVertexAttribArray(shader.va_texId);
                gl.vertexAttribPointer(shader.va_texId, 2, gl.FLOAT, false, 40, 12);
                gl.enableVertexAttribArray(shader.va_bones);
                gl.vertexAttribPointer(shader.va_bones, 4, gl.FLOAT, false, 40, 20);
                gl.enableVertexAttribArray(shader.va_boneNum);
                gl.vertexAttribPointer(shader.va_boneNum, 1, gl.FLOAT, false, 40, 36);
                // 设置索引
                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.ib);
                
                var material = materials.elements[mesh.mId];
                for ( var j = 0, rl = material.renderPass.length; j < rl; ++j ){
                    var pass = material.renderPass[j];
                    if (pass.tId > textures.elements.length || textures.elements[pass.tId] < 0){
                        continue;
                    }
                    
                    gl.uniform1f(shader.u_alphaTest, 0);
                    
                    // filterMode {
                    //  0 - Opaque
                    //  1 - 1bit Alpha
                    //  2 - Blend
                    //  3 - Additive
                    //  4 - AddAlpha
                    //  5 - Modulate
                    //  6 - Modulate2x
                    // }

                    switch (pass.filterMode) {
                    case 0:
                        gl.depthMask(1);
                        gl.disable(gl.BLEND);
                        break;
                    case 1:
                    case 4:
                        gl.depthMask(1);
                        gl.disable(gl.BLEND);
                        gl.uniform1f(shader.u_alphaTest, 1);
                        break;
                    case 2:
                        gl.depthMask(0);
                        gl.enable(gl.BLEND);
                        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
                        break;
                    case 3:
                        gl.depthMask(0);
                        gl.enable(gl.BLEND);
                        gl.blendFunc(gl.ONE, gl.ONE);
                        break;
                        /*
                    case 4:
                        gl.depthMask(0);
                        gl.enable(gl.BLEND);
                        gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
                        break;*/
                    case 5:
                        gl.depthMask(0);
                        gl.enable(gl.BLEND);
                        gl.blendFunc(gl.ZERO, gl.SRC_COLOR);
                        break;
                    case 6:
                        gl.depthMask(0);
                        gl.enable(gl.BLEND);
                        gl.blendFunc(gl.DST_COLOR, gl.SRC_COLOR);
                        break;
                    }

                    // ShadingFlags {
                    //  #1   - Unshaded
                    //  #2   - SphereEnvironmentMap
                    //  #4   - ???
                    //  #8   - ???
                    //  #16  - TwoSided
                    //  #32  - Unfogged
                    //  #64  - NoDepthTest
                    //  #128 - NoDepthSet
                    // }

                    if (pass.twoSided) {
                        gl.disable(gl.CULL_FACE);
                    } else {
                        gl.enable(gl.CULL_FACE);
                    }
                    
                    if (pass.noDepthTest) {
                        gl.disable(gl.DEPTH_TEST);
                    } else {
                        gl.enable(gl.DEPTH_TEST);
                    }
                    
                    if (pass.noDepthSet) {
                        gl.depthMask(0);
                    }
                    
                    // 设置纹理
                    gl.activeTexture(gl.TEXTURE0);
                    gl.bindTexture(gl.TEXTURE_2D, textures.elements[pass.tId].texture);
                    gl.uniform1i(shader.u_tex0, 0);
                    // 绘制图案
                    gl.drawElements(gl.TRIANGLES, mesh.drawCount, gl.UNSIGNED_SHORT, 0);
                }
            }
            
            //renderMeshJoin( mvp );
            //renderSkeleton( mvp );
        }
        
        function GetNodeChild(nodes, nodeId)
        {
            var childs = [];
            for(var i = 0; i < nodes.length; ++i){
                if(nodes[i].parentId == nodeId){
                    childs.push(nodes[i]);
                }
            }
            
            return childs;
        }
       
        function GetIntegerPart(number, out){
            var integer = Math.abs(number - Math.fract(number));
            out[0] = (number >= 0 ? 1 : 0);
            out[1] = (integer & 0x00ff0000) >> 16;
            out[2] = (integer & 0x0000ff00) >> 8;
            out[3] = (integer & 0x000000ff);
        }
        
        function GetDecimalPart(number, out){
            number = Math.abs(number);
            var a = Math.fract(number * 16777216.0);
            var b = Math.fract(number * 65536.0);
            var c = Math.fract(number * 256.0);
            var d = Math.fract(number);
            out[0] = 0;
            out[1] = (b - (a / 256.0))*256.0;
            out[2] = (c - (b / 256.0))*256.0;
            out[3] = (d - (c / 256.0))*256.0;
        }
        
        function Combination(data, decimal){
            return ((data[0] - 0.5 > 0) ? 1.0 : -1.0) * (data[1] * 65536.0 + data[2] * 256.0 + data[3] + decimal);
        }
        
        function Unpack(data){
            return (data[0]/256.0) / 16777216.0 + (data[1]/256.0) / 65536.0 + (data[2]/256.0) /256.0 + (data[3]/256.0);
        }
        
        function UploadBoneMatrix()
        {
            var gl = window["webgl"];
            var model = window["model"];
            var chacheNodeMatArray = model.chacheNodeMatArray;
            var numberOfBones = chacheNodeMatArray.length + 1;
            
            var maxVertexUniformVectors = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);
            if (BoneMatrixStoreUseTexture(gl)) {
                var maxTextureUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
                if(gl.support_OES_texture_float)
                {
                    if(model.boneTexture === undefined){
                        model.hwbones = new Float32Array(16 * numberOfBones);
                        model.boneTexture = gl.createTexture();
                        model.boneTextureSize = Math.max(2, Math.powerOfTwo(numberOfBones)) * 4;
                        model.texelFraction = 1 / model.boneTextureSize;
                        model.matrixFraction = model.texelFraction * 4;
                        
                        gl.activeTexture(gl['TEXTURE'+(maxTextureUnits-1)]);
                        gl.bindTexture(gl.TEXTURE_2D, model.boneTexture);
                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, model.boneTextureSize, 1, 0, gl.RGBA, gl.FLOAT, null);
                    }
                    
                    for(var i = 0; i < 16 * numberOfBones; ++i){
                        model.hwbones[i] = 0;
                    }
                    for (var i = 1, l = numberOfBones; i < l; i++) {
                        model.hwbones.set(MatrixTranspose(chacheNodeMatArray[i-1].m), i * 16);
                    }
                    
                    gl.activeTexture(gl['TEXTURE'+(maxTextureUnits-1)]);
                    gl.bindTexture(gl.TEXTURE_2D, model.boneTexture);
                    gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, model.hwbones.length / 4, 1, gl.RGBA, gl.FLOAT, model.hwbones);
                }
                else
                {
                    if(model.boneTexture === undefined){
                        model.hwbones = new Uint8Array(128 * numberOfBones);
                        model.boneTexture = gl.createTexture();
                        model.boneTextureSize = Math.max(2, Math.powerOfTwo(numberOfBones)) * 32;
                        model.texelFraction = 1 / model.boneTextureSize;
                        model.matrixFraction = model.texelFraction * 32;
                        
                        gl.activeTexture(gl['TEXTURE'+(maxTextureUnits-1)]);
                        gl.bindTexture(gl.TEXTURE_2D, model.boneTexture);
                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, model.boneTextureSize, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
                    }
                    
                    for(var i = 0; i < 128 * numberOfBones; ++i){
                        model.hwbones[i] = 0;
                    }

                    var offset = 128;
                    var integerPart = new Uint8Array(4);
                    var decimalPart = new Uint8Array(4);
                    var element;
                    for (var i = 1, l = numberOfBones; i < l; i++) {
                        for(var j = 0; j < 4; ++j){
                            for(var k = 0; k < 4; ++k){
                                element = chacheNodeMatArray[i-1].m[k*4+j];
                                GetIntegerPart(element, integerPart);
                                GetDecimalPart(element, decimalPart);
                                var x = Combination(integerPart, Unpack(decimalPart));
                                model.hwbones.set(integerPart, offset);
                                model.hwbones.set(decimalPart, offset+4);
                                offset += 8;
                            }
                        }
                    }
                    
                    gl.activeTexture(gl['TEXTURE'+(maxTextureUnits-1)]);
                    gl.bindTexture(gl.TEXTURE_2D, model.boneTexture);
                    gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, model.hwbones.length / 4, 1, gl.RGBA, gl.UNSIGNED_BYTE, model.hwbones);
                }
            } else {
                var shader = window["mdxShader"];
                var maxBoneMatrix = GetMaxNumOfBoneMatrix(gl);
                numberOfBones = Math.min(maxBoneMatrix, numberOfBones);
                model.hwbones = new Float32Array(16 * numberOfBones);
                for(var i = 0; i < 16 * numberOfBones; ++i){
                    model.hwbones[i] = 0;
                }
                for (var i = 1, l = numberOfBones; i < l; i++) {
                    model.hwbones.set(MatrixTranspose(chacheNodeMatArray[i-1].m), i * 16);
                }                
                gl.uniformMatrix4fv(shader.u_boneMatrixs, false, model.hwbones);
            }
        }
        
        function PlaySequence(index, time)
        {
            var model = window["model"];
            if(model.isLoad === false)
                return;
            
            var sequences = model.parser.chunks.SEQS;
            var nodes = model.parser.nodes;
            var privots = model.parser.chunks.PIVT;
            
            if (index >= sequences.length)
                return;
            
            var chacheNodeMatArray = model.chacheNodeMatArray;
            if (chacheNodeMatArray === undefined){
                model.chacheNodeMatArray = [];
                chacheNodeMatArray = model.chacheNodeMatArray;
                for(var i = 0; i < nodes.length; ++i){
                    chacheNodeMatArray.push(new Mat4x4());
                }
            }

            var sequence = sequences.elements[index];
            var startTime = sequence.interval[0];
            var endTime = sequence.interval[1];
            
            var interval = endTime - startTime;
            if(time > interval){
                time = time % interval;
            }
            time += startTime;
           
            var node;
            for(var i = 0; i < nodes.length; ++i)
            {
                node = nodes[i];
                if(node.parentId < 0)
                {// 计算Node变换矩阵
                    CalcLocalMatrix(nodes, privots, chacheNodeMatArray, node, time, startTime, endTime);
                }
            }
            
            var numAnim = 0;
            for(var i = 0; i < nodes.length; ++i)
            {
                node = nodes[i];
                if(node.hasAnim)
                {
                    ++numAnim;
                }
            }
            
            console.log("更新动画活动" +  numAnim + "根骨骼");
            
            UploadBoneMatrix();
        }
        
        function PlayParticle(index, time)
        {
            var particleEmitter = window["ParticleEmitter"];
            particleEmitter.Update(index, time);
        }
        
        function renderLineShape( shape, mvp )
        {
            var gl = window["webgl"];
            var shader = window["solidShader"];
            
            gl.useProgram(shader.program);
            gl.uniformMatrix4fv(shader.u_MVP, false, mvp);
            
            shape.renderLines(shader);
        }
        
        function renderMeshJoin( mvp )
        {
            var gl = window["webgl"];
            var shader = window["solidShader"];
            
            gl.useProgram(shader.program);
            gl.uniformMatrix4fv(shader.u_MVP, false, mvp);
        
            var painter = window["painter"];
            if (painter === undefined){
                window["painter"] = new Painter(gl);
                painter = window["painter"];
            }
            else{
                painter.ClearPoints();
                var model = window["model"];
                var parser  = model.parser;
                var privots = parser.chunks.PIVT.elements;
                var chacheNodeMatArray = model.chacheNodeMatArray;
                var finalPrivot;
                for (var i = 0, l = privots.length; i < l; ++i){
                    finalPrivot = chacheNodeMatArray[i].Transform(privots[i].data);
                    painter.AddPoint(finalPrivot[0], finalPrivot[1], finalPrivot[2]);
                }
            }
            
            gl.disable(gl.DEPTH_TEST);
            gl.depthMask(0);
            painter.RenderPoints(shader);
            gl.depthMask(1);
            gl.enable(gl.DEPTH_TEST);
        }
        
        function renderSkeleton( mvp )
        {
            var gl = window["webgl"];
            var shader = window["solidShader"];
            
            gl.useProgram(shader.program);
            gl.uniformMatrix4fv(shader.u_MVP, false, mvp);
            
            var painter = window["skeletonPainter"];
            if (painter === undefined){
                window["skeletonPainter"] = new Painter(gl);
                painter = window["skeletonPainter"];
           }else{
                painter.ClearLines();
                var model = window["model"];
                var chacheNodeMatArray = model.chacheNodeMatArray;
                var parser  = model.parser;
                var nodes = parser.nodes;
                var nodeNb = nodes.length;
                var privts = parser.chunks.PIVT.elements;
                for (var i = 0; i < nodeNb; ++i){
                    var node = nodes[i];
                    if (node.parentId === -1) {
                        //var pivt = pivts[node.objectId].data;
                        //painter.AddPoint(pivt[0], pivt[1], pivt[2]);
                    }
                    else{
                        var privt = privts[node.objectId].data;
                        var parentPrivt = privts[node.parentId].data;
                        var p1 = chacheNodeMatArray[node.parentId].Transform(parentPrivt);
                        var p2 = chacheNodeMatArray[node.objectId].Transform(privt);
                        painter.AddLine(p1[0], p1[1], p1[2], p2[0], p2[1], p2[2]);
                    }
                }
            }
            
            gl.disable(gl.DEPTH_TEST);
            gl.depthMask(0);
            painter.RenderPoints(shader);
            painter.RenderLines(shader);
            gl.depthMask(1);
            gl.enable(gl.DEPTH_TEST);
        }
        
        function renderParticle( mvp )
        {
            var gl = window["webgl"];
            var shader = window["particleShader"];
            var textures = window["textures"];
            if (textures === undefined || textures.elements.length == 0 || textures.elements[0] === -1)
                return;
                
            var camera = window["camera"];
            var view = new Mat4x4(LookAtRH(camera.position, camera.lookAt, new Vec3(0,0,1)));
            //var view = new Mat4x4(LookAtRH(camera.position, camera.lookAt, new Vec3(0,1,0)));
            var projection = new Mat4x4(PerspectiveRH(45.0, canvas.width/canvas.height, 1.0, 10000.0));
            
            gl.useProgram(shader.program)
            gl.uniformMatrix4fv(shader.u_MV, false, view.Transpose().m)
            gl.uniformMatrix4fv(shader.u_P, false, projection.Transpose().m)
            gl.uniform1f(shader.u_screenWidth, canvas.width);
            gl.uniform1f(shader.u_particleSize, 50.0);
            
            // 纹理变换矩阵
            var m1 = new Mat4x4();
            m1.Translate(-0.5, -0.5, 0.0)
            var m2 = new Mat4x4();
            m2.RotationZ(g_Time*0.02)
            m2.MultiplySelf(m1);
            m1.Translate(1.0, 1.0, 0.0)
            m1.MultiplySelf(m2);            
            gl.uniformMatrix4fv(shader.u_Tex0_Matrix, false, m1.Transpose().m)
            
            gl.activeTexture(gl.TEXTURE0);
            gl.bindTexture(gl.TEXTURE_2D, textures.elements[1].texture);
            
            var painter = window["particlePainter"];
            if (painter === undefined){
                window["particlePainter"] = new Painter(gl);
                painter = window["particlePainter"];
                painter.ClearPoints();
                for(var i = 0; i < 1000; ++i){
                    painter.AddPoint(Math.randomRange(-500.0, 500.0), Math.randomRange(-500.0, 500.0), Math.randomRange(-500.0, 500.0));
                }
            }else{

            }
            
            //gl.disable(gl.DEPTH_TEST);
            //gl.depthMask(0);
            //gl.enable(gl.POINT_SMOOTH);
            painter.RenderPoints(shader);
            //gl.depthMask(1);
            //gl.enable(gl.DEPTH_TEST);
        }
        
        function start() {
            window.addEventListener('gliready', function() {
                initialize();
            });
        }
        
        function initialize()
        {
            try{
                eruda.init();
                
                var canvas = document.getElementById("canvas");
                window["webgl"] = CreateWebGL(canvas);
                var gl = window["webgl"];
                if (gl){
                    window["mdxShader"] = CreateMdxShader(gl);
                    window["solidShader"] = CreateSolidShader(gl);
                    window["particleShader"] = CreateParticleShader(gl);
                }
                
                window["camera"] = {
                    position : new Vec3(350, 0, 350),
                    lookAt : new Vec3(-500, 0, -200)
                }
                
                var workarea = document.getElementById("work-area");
                var stats = new Stats();
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.top = '0px';
                workarea.appendChild( stats.domElement );
                
                var cube = new Cube(gl, 100, -100, 0, -100, 100, 200);
                //var cylinder = new Cylinder(gl, 0, 0, 100, 100, 100, 32);
                //var sphere = new Sphere(gl, 0, 0, 100, 32, 32, 100);
                
                window.addEventListener("resize", function(){ ResetViewport(canvas, gl); });
                ResetViewport(canvas, gl);

                function update() {
                    stats.update();
                    
                    var model = window["model"];
                    var textures = window["textures"];
                    var materials = window["materials"];
            
                    if(model === undefined || materials === undefined || textures === undefined ||
                       model.isLoad !== true || materials.isLoad !== true || textures.elements.length <= 0)
                        return;
                
                    // 更新动作
                    PlaySequence(g_AnimatinIndex, g_Time);
                    PlayParticle(g_AnimatinIndex, g_Time);
                    g_Time += 15 * g_Speed;
                }
                
                function render() {
                    var gl = window["webgl"];
                    
                    // https://www.opengl.org/wiki/FAQ#Masking
                    //gl.depthMask(1);
                    
                    gl.clearColor(0.0, 0.141, 0.141, 1.0);
                    gl.clearDepth(1.0);
                    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
                    // 计算矩阵
                    var camera = window["camera"];
                    var view = new Mat4x4(LookAtRH(camera.position, camera.lookAt, new Vec3(0,0,1)));
                    //var view = new Mat4x4(LookAtRH(camera.position, camera.lookAt, new Vec3(0,1,0)));
                    var projection = new Mat4x4(PerspectiveRH(45.0, canvas.width/canvas.height, 1.0, 10000.0));
                    var vp = projection.Multiply(view);
                    var world = new Mat4x4();
                    var mvp;// = vp.Transpose().m;
                    
                    
                    var step = 2;
                    for (var i = -step; i <= 0; ++i) {
                        for (var j = -step; j <= step; ++j) {
                            world.Identity().Translate(i * 50, j * 50, 0);
                            mvp = (vp.Multiply(world)).Transpose().m;
                            renderMesh(mvp);
                        }
                    }
                    
                    
                    //renderLineShape(cube, mvp);
                    //renderParticle(mvp);
                }
                
                var requestAnimFrame = (function() {
                    return window.requestAnimationFrame ||
                         window.webkitRequestAnimationFrame ||
                         window.mozRequestAnimationFrame ||
                         window.oRequestAnimationFrame ||
                         window.msRequestAnimationFrame ||
                         function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
                           window.setTimeout(callback, 1000/60);
                         };
                })();
                
                (function step() {
                    update();
                    render();
                    
                    requestAnimFrame(step);
                }());
          
                // 加载模型列表
                LoadMPQList();
                // 加载模型
                //LoadModel("MPQ/" + "Units/Creeps/GolemStatue/GolemStatue.mdx");
                //LoadModel("MPQ/" + "Units/Creeps/GreenDragon/GreenDragon.mdx");
                LoadModel("MPQ/" + "Units/Human/Arthas/Arthas.mdx");
                
                //var available_extensions = gl.getSupportedExtensions();
                //alert(available_extensions);
            }catch(error){
                alert(error.name + "\n" + error.number + "\n" + error.description + "\n" + error.message);
            }
        }
        
    </script>

    
    <script>
        var gliEmbedDebug = true;
    </script>
    <script src="./core/embed.js"></script>
   

    </head>
  
    <body onload="initialize()">
        <div id="menu-bar">
            <div class="menu">
                <div class="title">文件</div>
                
                <div class="options" id="options" >
                    <div class="option" onclick="onclick1()" >打开(F)</div>
                    <hr/>
                    <div class="option">保存</div>
                </div>
            </div>
            <div class="menu">
                <div class="title">编辑</div>
                
                <div class="options">
                    <div class="option">撤销</div>
                    <div class="option">恢复</div>
                    <hr/>
                    <div class="option">全选</div>
                    <div class="option">复制</div>
                    <div class="option">粘贴</div>
                </div>
            </div>
            <div class="menu">
                <div class="title">关于</div>
                
                <div class="options">
                    <div class="option">作者</div>
                    <hr/>
                    <div class="option">更新</div>
                    <div class="option">签证</div>
                </div>
            </div>
        </div>

        <div id = "work-area">
            <canvas id="canvas"></canvas>
            <div id = "outline">
                <div class="panel">
                    <div class="head" id="t6" onclick="onClick3(this)" style="font-weight:bold;cursor:pointer;" >◢
                        <div class="name" id="t6_title">动画</div>
                    </div>
                    <div class="content" id="t6_content" >内容</div>
                </div>
                <div class="panel">
                    <div class="head" id="t1" onclick="onClick3(this)" style="font-weight:bold;cursor:pointer;" >◢
                        <div class="name" id="t1_title">材质</div>
                    </div>
                    <div class="content" id="t1_content" >内容
                    </div>
                </div>
                <div class="panel">
                    <div class="head" id="t2" onclick="onClick3(this)" style="font-weight:bold;cursor:pointer;" >◢
                        <div class="name" id="t2_title">几何</div>
                    </div>
                    <div class="content" id="t2_content" >内容</div>
                </div>
                <div class="panel">
                    <div class="head" id="t3" onclick="onClick3(this)" style="font-weight:bold;cursor:pointer;" >◢
                        <div class="name" id="t3_title">纹理</div>
                    </div>
                    <div class="content" id="t3_content" >
                    </div>
                </div>
                <div class="panel">
                    <div class="head" id="t4" onclick="onClick3(this)" style="font-weight:bold;cursor:pointer;" >◢
                        <div class="name" id="t4_title">块</div>
                    </div>
                    <div class="content" id="t4_content" >内容</div>
                </div>
                <div class="panel">
                    <div class="head" id="t5" onclick="onClick3(this)" style="font-weight:bold;cursor:pointer;" >◢
                        <div class="name" id="t5_title">骨骼</div>
                    </div>
                    <div class="content" id="t5_content" >内容</div>
                </div>
                <div id="hidden outline" onclick="onClick2()" style="background:#ff0;position:absolute;width:16px;height:4%;top:48%;padding-top:4px;left:74%;cursor:pointer;">►</div>
            </div>
            <div id="show ountline" onclick="onClick2()" style="background:#ff0;position:absolute;width:16px;right:0%;height:4%;top:48%;padding-top:4px;cursor:pointer;display:none">◄</div>
        </div>

        <div id= "status-bar">
            <div id="status-info" class="msg">status bar: show some massage.</div>
            <div id="beiAn">
                <div style="padding:4px; font-size: 12px;">
                备案编号:<a href="http://www.miibeian.gov.cn/" style="font-size: 12px;">陕ICP备16018089号-1</a>
                </div>
            </div>
        </div>
    </body>
</html>